package com.stox.ui.javafx.charting.model.uiunit;

import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.paint.Color;

import com.stox.ui.javafx.charting.model.plot.AbstractPlot;
import com.stox.ui.javafx.charting.model.plot.AbstractPrimaryPlot;
import com.stox.ui.javafx.charting.widget.Chart;

public abstract class AbstractUiUnit<T,
			W extends Chart<U>, 
			V extends AbstractUiUnit<T,W,V, U>, 
			U extends AbstractPlot<T,W,V,U>>{

	protected final U plot;
	
	protected double x;
	
	protected double width;
	
	protected final int index;
	
	protected Color color;
	
	protected final T model;
	
	private Color backgroundColor;
	
	public AbstractUiUnit(T model, U plot, int index) {
		this.model = model;
		this.plot = plot;
		this.index = index;
	}

	public void update() {
		updateX();
		updateWidth();
	}
	
	protected void updateX() {
		if(index < getPlot().getChart().getChartingView().getEndIndex()-1) {
			AbstractUiUnit<T,W,V,U> previousUiUnit = getPlot().getUiUnits().get(index+1);
			x = previousUiUnit.x + previousUiUnit.width;
		}else {
			x = getPlot().getChart().getCanvas().getLayoutX();
		}
	}
	
	protected void updateWidth() {
		AbstractPrimaryPlot<?,?,?,?> abstractPrimaryPlot = getPlot().getChart().getChartingView().getPrimaryChart().getFrontPlot();
		width = abstractPrimaryPlot.getUiUnits().get(index).width;
	}
	
	public abstract void paint();
	
	public void paintBackground() {
		Canvas canvas = getPlot().getChart().getCanvas();
		GraphicsContext gc = canvas.getGraphicsContext2D();
		gc.setFill(backgroundColor);
		gc.fillRect(x, canvas.getLayoutY(), x+width, canvas.getLayoutY()+canvas.getHeight());
	}
	
	public double height(double value) {
		double height = getPlot().getChart().getCanvas().getHeight();
		if(getPlot().getChart().getChartingView().getPrimaryChart().isSemilog()) {
			return (Math.log(value) - Math.log(getPlot().getLowest()))*(getPlot().getChart().getCanvas().getHeight()/(Math.log(getPlot().getHighest()) - Math.log(getPlot().getLowest())));
		}else {
			return height - ((value - getPlot().getLowest())*(height/(getPlot().getHighest() - getPlot().getLowest())));
		}
	}
	
	public double price(double value){
		double height = getPlot().getChart().getCanvas().getHeight();
		if(getPlot().getChart().getChartingView().getPrimaryChart().isSemilog()) {
			return Math.log(getPlot().getLowest()) + ((height - value)*(Math.log((getPlot().getHighest()) - Math.log(getPlot().getLowest()))))/height;
		}else {
			return getPlot().getLowest() + ((height - value)*((getPlot().getHighest() - getPlot().getLowest())))/height;
		}
	}
	
	public int getIndex() {
		return index;
	}
	
	public Color getColor() {
		return color;
	}

	public void setColor(Color color) {
		this.color = color;
	}

	public U getPlot() {
		return plot;
	}

	public T getModel() {
		return model;
	}
	
	public double getX() {
		return x;
	}

	public void setX(double x) {
		this.x = x;
	}

	public double getWidth() {
		return width;
	}

	public void setWidth(double width) {
		this.width = width;
	}
	
	
	public Color getBackgroundColor() {
		return backgroundColor;
	}

	public void setBackgroundColor(Color backgroundColor) {
		this.backgroundColor = backgroundColor;
	}

}
